package com.carleasoft.mps.adu.common.aspect;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.carleasoft.mps.adu.common.annotaion.OpImgAnnotation;
import com.carleasoft.mps.adu.common.feign.FileManage;
import com.carleasoft.mps.adu.common.feign.RemoteFileService;
import com.carleasoft.mps.core.result.R;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>Description：</p>
 *
 * @author lijinwen
 * @date 2021/6/9 16:44
 */
@Aspect
@Component
public class OpImgAspect {
    private static final Logger log = LoggerFactory.getLogger(OpImgAspect.class);

    private String operationKeyword;
    @Autowired
    private RemoteFileService remoteFileService;

    /**
     * @Description: 定义切入点
     */
    //被注解CustomAopAnnotation表示的方法
    @Pointcut("@annotation(com.carleasoft.mps.adu.common.annotaion.OpImgAnnotation)")
    public void pointCut() {
        log.info("执行了pointCut()");
    }

    /**
     * @Description: 定义前置通知
     */
    @Before("pointCut()")
    public void before(JoinPoint joinPoint) throws Throwable {
    }

    @Around("pointCut()")
    public R afterReturning(ProceedingJoinPoint joinPoint) throws Throwable {
        OpImgAnnotation controllerLog = getAnnotationLog(joinPoint);
        if (controllerLog == null) {
            return R.ok();
        }
        // 获取修改的字段
        this.operationKeyword = controllerLog.value();
        // 处理完请求，返回内容
        R resultBody = (R) joinPoint.proceed();
        if (resultBody.getCode().equals("000000")) {
            // 修改返回值
            Object data = resultBody.getData();
            if (null != data) {
                if (data.getClass().isArray()) {
                    // data为数组
                    return R.ok();
                } else {
                    Map<String, Object> mapOj = new HashMap<>();
                    Field[] fields = data.getClass().getDeclaredFields();
                    for (Field field : fields) {
                        field.setAccessible(true);
                        mapOj.put(field.getName(), field.get(data));
                    }
                    if(mapOj.containsKey("records")) {
                        // data 为分页对象
                        List<Object> records = (List<Object>) mapOj.get("records");
                        List<Object> objects = buildRecordData(controllerLog.value(), records);
                        mapOj.put("records",objects);
                        resultBody.setData(mapOj);
                        return resultBody;
                    } else {
                        Map<String, Object> resData = buildData(controllerLog.value(), data);
                        resultBody.setData(resData);
                        // data为对象
                        return resultBody;
                    }

                }
            }

        } else {
            return resultBody;
        }
        return resultBody;
    }

    /**
     * 是否存在注解，如果存在就获取
     */
    private OpImgAnnotation getAnnotationLog(JoinPoint joinPoint) {
        log.info("连接点值：" + joinPoint.toString());
        Signature signature = joinPoint.getSignature();
        log.info("signature的json值：" + JSON.toJSONString(signature));
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        log.info("method的json值：" + JSON.toJSONString(method));
        if (method != null) {
            return method.getAnnotation(OpImgAnnotation.class);
        }
        return null;
    }

    private Map<String, Object> buildData(String keyList, Object data) throws Exception {
        Map<String, Object> res = new HashMap<>();
        String[] split = keyList.split(",");
        Field[] fields = data.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            res.put(field.getName(), field.get(data));
        }
        for (String key : split) {
            String files = (String)res.get(key);
            if(StringUtils.isNotBlank(files)){
                List<String> fileList = JSONArray.parseArray(files, String.class);
                List<FileManage> resFile = remoteFileService.getFileList(fileList).getData();
                if(null != resFile && resFile.size()>0){
                    resFile.stream().forEach(t->t.setUrl(t.getFilePath()));
                    resFile.stream().forEach(t->t.setName(t.getMinioFileName()));
                    res.put(key,JSONArray.toJSONString(resFile));
                }
            }
        }
        return res;
    }
    private List<Object> buildRecordData(String keyList,List<Object> records)throws Exception{
        List<Object> res = new ArrayList<>();
        for (Object object : records) {
            Map<String, Object> itemObj = new HashMap<>();
            Field[] itemField = object.getClass().getDeclaredFields();
            for (Field field : itemField) {
                field.setAccessible(true);
                itemObj.put(field.getName(), field.get(object));
            }
            String[] split = keyList.split(",");
            for (String key : split) {
                String files = (String)itemObj.get(key);
                if(null != files && files.startsWith("[")){
                    List<String> fileList = JSONArray.parseArray(files, String.class);
                    List<FileManage> resFile = remoteFileService.getFileList(fileList).getData();
                    if(null != resFile && resFile.size()>0){
                        resFile.stream().forEach(t->t.setUrl(t.getFilePath()));
                        resFile.stream().forEach(t->t.setName(t.getMinioFileName()));
                        itemObj.put(key,JSONArray.toJSONString(resFile));
                    }
                }
            }
            res.add(itemObj);
        }
        return res;
    }
}
